#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QTreeWidgetItem>
#include <iostream>
#include <QMessageBox>
#include "dependencydialog.h"
#include <sstream>
#include <QInputDialog>
#include <stdlib.h>
#include <mutex>
#include "threadqueue.h"
#include <QProgressDialog>
#include <QProgressBar>
using namespace SwarmHostSystemCommands;

//Helper
std::string removeNewlines(std::string str){
    size_t pos = str.find('\n');
    while(str.size() > 1 && pos != std::string::npos){
        str.replace(pos,1," ");
        pos = str.find('\n');
    }
    return str;
}



MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    files2push("")
{
    // Set up ui (auto-generated)
    ui->setupUi(this);

    // Load Settings
    settings = new QSettings("CSRinc","SwarmGUI");

    // Get IPs from settings and ask user if they want to edit them.
    bool ok;
    QString ips = settings->value("Network/ips").value<QString>();
    ips = QInputDialog::getMultiLineText(0,tr("Set IPs"),tr("Swarm Robots IP List"),ips,&ok);

    // Initialize SwarmNet network
    if (ips.isEmpty()){
        try{
            SwarmNet = new Network();
        }
        catch(const std::exception & err){
            messageUserDialog(DialogType::ERROR_SHDT,string("There failed to connect to Network: ")
                              + err.what(),"");
        }
    }
    else{
        // Save IPs in settings for access later
        settings->setValue("Network/ips",ips);

        // Parse using stringstream
        stringstream ipStream(ips.toStdString());
        while(ipStream.eof() == false){
            string ip;
            ipStream >> ip;
            ipsVector.push_back(ip);
        }
        // Construct network
        try{
            SwarmNet = new Network(ipsVector);
        }
        catch(const std::exception & err){
            messageUserDialog(DialogType::ERROR_SHDT,string("There failed to connect to Network: ")
                              + err.what(),"");
        }
    }

    // Configure as host
    SwarmNet->youAreHost(SwarmOS::OS_INSTRUCTION + SwarmOS::NET_DATA_ID, SwarmOS::OS_INSTRUCTION + SwarmOS::NET_DATA_IP, SwarmOS::OS_INSTRUCTION + SwarmOS::NET_DATA_IP_SIZE);

    // launch communication thread for use (controls receipt of messages
    // using SwarmNet)
    communicationThread =
            new std::thread(&MainWindow::communicationProcess,this);


    // Populate debug dialog map for use later
    for (size_t i = 0; i < ipsVector.size(); i++){
        dbgDlgs[ipsVector[i]] = NULL;
    }


}



MainWindow::~MainWindow()
{

    delete ui;
    delete SwarmNet;

    // Kill thread
    killCommunicationThread = true;
    communicationThread->join();

    delete communicationThread;
    delete settings;

    for (size_t i = 0; i < ipsVector.size(); i++){
        if (dbgDlgs[ipsVector[i]] != NULL){
            delete dbgDlgs[ipsVector[i]];
            dbgDlgs[ipsVector[i]] = NULL;
        }
    }
}

void MainWindow::refreshSettingDependentObjects(){


    // Kill thread
    killCommunicationThread = true;
    communicationThread->join();

    delete communicationThread;
    delete SwarmNet;

    for (size_t i = 0; i < ipsVector.size(); i++){
        if (dbgDlgs[ipsVector[i]] != NULL){
            delete dbgDlgs[ipsVector[i]];
            dbgDlgs[ipsVector[i]] = NULL;
        }
    }


    QString ips = settings->value("Network/ips").value<QString>();
    // Initialize SwarmNet network
    if (ips.isEmpty()){
        try{
            SwarmNet = new Network();
        }
        catch(...){
            messageUserDialog(DialogType::ERROR_SHDT,string("Failed to connect to Network!"),"");
        }
    }
    else{
        // Save IPs in settings for access later
        settings->setValue("Network/ips",ips);

        // Parse using stringstream
        stringstream ipStream(ips.toStdString());
        while(ipStream.eof() == false){
            string ip;
            ipStream >> ip;
            ipsVector.push_back(ip);
        }
        // Construct network
        try{
            SwarmNet = new Network(ipsVector);
        }
        catch(...){
            messageUserDialog(DialogType::ERROR_SHDT,string("Failed to connect to Network!")
                              ,"");
        }
    }

    // Configure as host
    SwarmNet->youAreHost(SwarmOS::OS_INSTRUCTION + SwarmOS::NET_DATA_ID, SwarmOS::OS_INSTRUCTION + SwarmOS::NET_DATA_IP, SwarmOS::OS_INSTRUCTION + SwarmOS::NET_DATA_IP_SIZE);

    // launch communication thread for use (controls receipt of messages
    // using SwarmNet)
    killCommunicationThread = false;
    communicationThread =
            new std::thread(&MainWindow::communicationProcess,this);


    // Populate debug dialog map for use later
    for (size_t i = 0; i < ipsVector.size(); i++){
        dbgDlgs[ipsVector[i]] = NULL;
    }
}

void MainWindow::on_browseButton_pressed()
{
    static QString path = "/home/";
    QStringList files = QFileDialog::getOpenFileNames(
                             this,
                             "Select one or more files to open",
                             path,
                             "Code (*.c *.cpp)");
    if (!files.isEmpty()){
        for (int i = 0; i < files.size(); i++){
            QList<QListWidgetItem *> items =
                    ui->fileList->findItems(files[i],Qt::MatchExactly);
            if (!items.isEmpty()){
                files.removeOne(files[i]);
            }
        }
        if (!files.isEmpty()){
            ui->fileList->addItems(files);

            QFileInfo file(files[0]);
            path = file.absolutePath();
        }
    }

}



void MainWindow::on_dependencyButton_pressed()
{
    DependencyDialog dlg;
    dlg.setModal(true);
    dlg.setInclude(compInfo.INCLUDE);
    dlg.setLibrary(compInfo.LIBS);
    dlg.setCFlags(compInfo.CFLAGS);
    dlg.exec();
    compInfo.INCLUDE = dlg.getInclude();
    compInfo.LIBS = dlg.getLibrary();
    compInfo.CFLAGS = dlg.getCFlags();
    settings = new QSettings("CSRinc","SwarmGUI");


}

void addTextHelper(QPlainTextEdit * edit, string text){
    QString tempText = edit->toPlainText();
    tempText += QString::fromStdString("\n\n" + text);
    edit->setPlainText(tempText);
    edit->update();
}

void MainWindow::on_compileButton_pressed()
{

    // Find all items that match ".c" (they all should).
    QList<QListWidgetItem *> fileItems = ui->fileList->findItems(".c",Qt::MatchContains);

    if(!fileItems.isEmpty()){

         QString inFiles = "";
         QString outFilesMoved = "";
        //Extract them from the QList
        for (int i = 0; i < fileItems.size(); i++){
            QFileInfo info(fileItems[i]->text());

            inFiles += info.absoluteFilePath() + " ";
            outFilesMoved += (info.baseName() + ".o ");
        }
        std::string cflags = removeNewlines(compInfo.CFLAGS.toStdString());
        std::string includes = removeNewlines(compInfo.INCLUDE.toStdString());


        std::string finalInput = cflags + " " + includes + " " + COMPILE + " "+
                inFiles.toStdString();

        string output = CrossCompileFiles(cflags,includes,inFiles.toStdString());

        addTextHelper(ui->consoleOutputText, GCC + finalInput);
        addTextHelper(ui->consoleOutputText, output);

        files2push = outFilesMoved.toStdString();
    }

}

void MainWindow::on_push2SwarmButton_pressed()
{
    QProgressBar * bar = new QProgressBar();

    ui->statusBar->addWidget(bar);
    bar->setMinimum(0);
    bar->setMaximum(100);
    pushAndLinkProcess(bar);
    ui->statusBar->removeWidget(bar);
    delete bar;

}

void MainWindow::pushAndLinkProcess(QProgressBar * bar){
    vector<string> currentIPs;
    if (ui->robotIPCombo->currentText().toStdString() == "All"){
        currentIPs = ipsVector;
    }
    else{
        currentIPs.push_back(ui->robotIPCombo->currentText().toStdString());
    }

    bar->setValue(0);
    for (size_t i = 0; i < currentIPs.size(); i++){
        //bar->setLabelText("Push to Swarm: Robot" + QString::fromStdString(ipsVector[i]));
        bar->update();
        string ip = currentIPs[i];
        std::stringstream stream(files2push);
        string finalObjectFiles = "";
        string output = "";

        if (files2push != ""){
            /*if (bar->wasCanceled()){
                bar->close();
                return;
            }*/
            // Get the first file
            string fname = "";
            getline(stream,fname,' ');
            // This loop pushes each file to the object folder
            while(fname != ""){
                QString temp = QFileInfo(QString::fromStdString(fname)).fileName();

                // Save object file names to make compilation easy.
                finalObjectFiles += " " + OBJ_FOLDER + temp.toStdString();
                output = MoveFileFromHostToSwarm(ip, fname, OBJ_FOLDER);
                if (output.find("Terminated") != string::npos){
                    break;
                }

                addTextHelper(ui->consoleOutputText,output);
                getline(stream,fname,' ');
            }
            if (output.find("Terminated") != string::npos){
                output += "Failed to connect to " + ip + "!\n";

                addTextHelper(ui->consoleOutputText, output);

                bar->setValue(100 * (i + 1) / currentIPs.size());
                bar->update();
                continue;
            }
            else{
                bar->setValue(25 * (i + 1) / currentIPs.size());
                bar->update();
                /*if (bar->wasCanceled()){
                    bar->close();
                    return;
                }*/
            }
            //
            string outputFilename = ui->outputFilename->text().toStdString();
            if (ui->soRadioButton->isChecked()){
                // Make the filename a shared object filename
                outputFilename = LIB_FOLDER + "lib" + outputFilename + ".so";

                output = CreateSharedObjectFile(ip, outputFilename,finalObjectFiles,
                                    removeNewlines(compInfo.LIBS.toStdString()));
                if (output.find("Terminated") != string::npos){
                    output += "Failed to connect to " + ip + "!\n";

                    addTextHelper(ui->consoleOutputText,output);

                    bar->setValue(100 * (i + 1) / currentIPs.size());
                    continue;
                }
                bar->setValue(50 * (i + 1) / currentIPs.size());
                bar->update();
                /*if (bar->wasCanceled()){
                    bar->close();
                    return;
                }*/

                addTextHelper(ui->consoleOutputText, output);


                // Just create links for all objects in the library folder
                output = UpdateLibraries(ip, LIB_FOLDER + "*");

                addTextHelper(ui->consoleOutputText, output);


                bar->setValue(100 * (i + 1) / currentIPs.size());
                bar->update();

            }
            else{
                outputFilename = BIN_FOLDER + outputFilename;
                /*if (bar->wasCanceled()){
                    bar->close();
                    return;
                }*/
                output = createExecutable(ip, outputFilename,finalObjectFiles,
                                 removeNewlines(compInfo.LIBS.toStdString()));
                if (output.find("Terminated") != string::npos){
                    output += "Failed to connect to " + ip + "!\n";

                    addTextHelper(ui->consoleOutputText, output);

                    bar->setValue(100 * (i + 1) / currentIPs.size());
                    bar->update();
                    continue;
                }
                bar->setValue(100 * (i + 1) / currentIPs.size());
                bar->update();

                addTextHelper(ui->consoleOutputText, output);

            }




        }
        else{

            addTextHelper(ui->consoleOutputText, "Please compile before you try to push!");
        }

    }

    string output = "++++++ END OF PUSH ++++++";
    addTextHelper(ui->consoleOutputText, output);
    bar->close();
}


void MainWindow::on_debugButton_clicked()
{
    // Get currently selected robot
    QList<QTreeWidgetItem *> items = ui->availableRobotsTree->selectedItems();
    if (!items.isEmpty()){
        for (int i = 0; i < items.size(); i++){
            // Get robots IP address
            string robotIP = items[i]->text(2).toStdString();
            bool robotOn = (items[i]->text(1).toStdString() == "On");
            // Use ip to either create a new window or raise the current one
            if (dbgDlgs[robotIP] == NULL && robotOn){
                //writeMessage(robotIP,DEBUG);
                //todo: have debug dialog get debug info on load
                dbgDlgs[robotIP] = new DebugWindow(this,ui->availableRobotsTree->indexOfTopLevelItem(items[i])+1);
                dbgDlgs[robotIP]->setWindowTitle("Debug: " + items[i]->text(0));
                dbgDlgs[robotIP]->show();
            }
            else if(robotOn){
                dbgDlgs[robotIP]->raise();
            }
            else{
                messageUserDialog(WARN_SHDT,items[i]->text(0).toStdString()+
                                  " is not connected to the network","");
            }
        }
    }
    else{
        QMessageBox msg;
        msg.setInformativeText("Please select a robot to debug!");
        msg.exec();
    }
 }


void MainWindow::closeDebugWindow(const int botnum)
{
    int robotIdx = botnum - 1;
    if (dbgDlgs[ipsVector[robotIdx]] != NULL){
        delete dbgDlgs[ipsVector[robotIdx]];
        dbgDlgs[ipsVector[robotIdx]] = NULL;
    }
}


void MainWindow::on_commandButton_clicked()
{
    // Get selected robots
    QList<QTreeWidgetItem *> items = ui->availableRobotsTree->selectedItems();

    // Send message to each selected robot
    if (items.isEmpty()){
        messageUserDialog(DialogType::WARN_SHDT,
            "No robot selected. Please select a robot!",
            "");
        return;//We don't need to do anything so return;
    }
    //
    for (int i = 0; i < items.size(); i++){
        string robotIP = items[i]->text(2).toStdString();

        // Make sure to clear the errors so we can tell if a network error happened
        errno = 0;
        // Send Message
        if (items[i]->text(1) == "On"){
            writeMessage(robotIP, ui->commandEdit->text().toStdString());
        }
        else{
            messageUserDialog(DialogType::WARN_SHDT,
                (items[i]->text(0)+" is off! Cannot command.").toStdString(),
                "");
        }
    }

}



void MainWindow::on_playButton_toggled(bool checked)
{
    if(checked){
        //TODO: Do play stuff

    }
    else{
        // TODO: Do stop stuff
    }
}

void MainWindow::communicationProcess(){
    bool isGettingDebugImgs = false;
    while(killCommunicationThread == false){
        //Get Swarm Robots' Statuses
        //TODO: How to get statuses?

        // Set available robots and algorithms
        QStringList robot;
        static QList<QTreeWidgetItem *> widgetList;

        // Get Messages from network

        vector<vector<string> > messages = receiveMessage();

        if (widgetList.isEmpty()){
            // Setup Widgets for first time
            bool wasConnection = false;
            if (!ipsVector.empty()){
                ui->robotIPCombo->clear();
                ui->robotIPCombo->addItem(QString::fromStdString("All"));
            }
            for (size_t i = 0; i < ipsVector.size(); i++){
                ui->robotIPCombo->addItem(QString::fromStdString(ipsVector[i]));
                string num;
                num  = itoa(i + 1);
                robot.clear();
                if (SwarmNet->isConnected(i+1)){
                    wasConnection = true;
                    robot << QString::fromStdString("Robot" + string(num)) << "On"
                             << QString::fromStdString(ipsVector[i]);
                    widgetList.append(new QTreeWidgetItem(robot));
                }
                else{
                    robot << QString::fromStdString("Robot" + string(num)) << "Off"
                             << QString::fromStdString(ipsVector[i]);
                    widgetList.append(new QTreeWidgetItem(robot));
                }
                // Use i - 1 because the widgets start at zero no one
                ui->availableRobotsTree->addTopLevelItem(widgetList[i]);
            }
            // Wait for robots to communicate
            while(killCommunicationThread == false &&
                  wasConnection && messages.empty()){
                messages = receiveMessage();
            }
            if (!messages.empty()){
                stringstream parseMessage(messages[0][0]);
                string algorithm = "";
                while (parseMessage.eof() == false){
                    getline(parseMessage,algorithm,',');
                    QTreeWidgetItem * item = new QTreeWidgetItem();
                    item->setText(0,QString::fromStdString(algorithm));
                    item->setText(1,QString::fromStdString("Available"));
                    ui->algorithmTree->addTopLevelItem(item);
                }
            }




        }

        else if(!messages.empty()) {
            // Since there are no changes and the SwarmNet is initialized parse
            // messages
            for (size_t i = 0; i < messages.size(); i++){
                vector <string> message = messages[i];
                // Send all messages for a specific robot to debug window
                // if it exists                
                if(dbgDlgs.count(message[1]) != 0 &&
                        dbgDlgs[message[1]] != NULL )
                {
                    // don't display debug image data!  Set isGettingDebugImgs when DEBUG_IMG_HDR comes, keep it set until DONE comes
                    isGettingDebugImgs = message[0] != SwarmOS::NET_DATA_DONE && (isGettingDebugImgs || message[0] == SwarmOS::DEBUG_IMG_HDR);
                    // send message, then add to messageQueue
                    // if message is DONE, will be zapped on queue -- can't add zapped message!
                    // see DebugWindow::waitAndProcessReturns()
                    if (!isGettingDebugImgs && message[0].find(SwarmOS::SWARM_DATA) != 0)
                    {
                        // skip OS DATA -- user should never see
                        dbgDlgs[message[1]]->addMessage(message);
                    }
                    dbgDlgs[message[1]]->messageQueue.push_back(message);
                }
                // skip OS DATA -- used by debug GUI, user should never see
                else if (isGettingDebugImgs || message[0].find(SwarmOS::SWARM_DATA) == 0) {}
                // Otherwise display messages
                else{
                    ui->controlPanelConsole->append(
                                QString::fromStdString(message[1] +
                                ": " + message[0]
                            ));

                }

            }
        }
        else if (false && refreshSwarmNet() == true){
            ui->availableRobotsTree->clear();
            for (size_t i = 0; i < ipsVector.size(); i++){
                ui->robotIPCombo->addItem(QString::fromStdString(ipsVector[i]));
                robot.clear();
                string num;
                num  = itoa(i + 1);

                if (SwarmNet->isConnected(i+1)){
                    robot << QString::fromStdString("Robot" + string(num)) << "On"
                             << QString::fromStdString(ipsVector[i]);
                    if(ui->availableRobotsTree->topLevelItem(i) != NULL &&
                            ui->availableRobotsTree->topLevelItem(i)->text(2) == "Off"){
                        writeMessage(ipsVector[i],"");
                    }

                    widgetList[i]->setText(0,robot[0]);
                    widgetList[i]->setText(1,robot[1]);
                    widgetList[i]->setText(2,robot[2]);

                }
                else{
                        robot << QString::fromStdString("Robot" + string(num)) << "Off"
                                 << QString::fromStdString(ipsVector[i]);
                        widgetList[i]->setText(0,robot[0]);
                        widgetList[i]->setText(1,robot[1]);
                        widgetList[i]->setText(2,robot[2]);
                }

                ui->availableRobotsTree->addTopLevelItem(widgetList[i]);
            }
        }



    }
}

void MainWindow::on_removeSelectedFIle_pressed()
{
    const int EMPTY_ROW = -1;
    // Remove the item selected by the user to remove

    int row = ui->fileList->currentRow();

    if (row != EMPTY_ROW){

        delete ui->fileList->takeItem(row);

    }
}

QMessageBox::StandardButton MainWindow::messageUserDialog(DialogType type,string message,string title){
    QMessageBox::StandardButton val = QMessageBox::Yes;
    QMessageBox messageBox;
    if (type == DialogType::ERROR_SHDT){
        messageBox.critical(0,"Error", QString::fromStdString(message));
    }
    else if(type == DialogType::WARN_SHDT){
        messageBox.warning(0,"Warning", QString::fromStdString(message));
    }
    else if(type == DialogType::QUEST_SHDT){
        val = messageBox.question(0,QString::fromStdString(title),
                            QString::fromStdString(message));
    }
    else{
        messageBox.information(0,QString::fromStdString(title),
                               QString::fromStdString(message));
    }
    messageBox.setFixedSize(500,200);
    messageBox.setModal(true);
    return val;
}


void MainWindow::on_fileList_doubleClicked(const QModelIndex &)
{
    if (ui->fileList->currentItem() != NULL){
        string command = TEXT_EDITOR + " " +
                ui->fileList->currentItem()->text().toStdString() + "&";
        system(command.c_str());
    }
}





void MainWindow::on_saveSettingsButton_clicked()
{
    QString projectName = ui->projectEdit->text();
    QStringList projectNames = settings->value("ProjectNames").value<QStringList>();


    if (projectNames.contains(projectName)){
        QMessageBox::StandardButton val;
        val = messageUserDialog(DialogType::QUEST_SHDT,projectName.toStdString() +
                                        " already exists. Do you wish to overwrite it?",
                                        "Overwrite Project?");
        if (val == QMessageBox::No){
            return;
        }
    }
    else{
        projectNames << projectName;
    }
    QStringList fileList;

    int i = 0;
    QListWidgetItem * item = ui->fileList->item(i);
    while(item != NULL){
        fileList << item->text();
        i++;
        item = ui->fileList->item(i);

    }
    settings->setValue(projectName+ "/" + "InputFiles",fileList);
    settings->setValue(projectName+ "/" + "INCLUDE",compInfo.INCLUDE);
    settings->setValue(projectName+ "/" + "CFLAGS",compInfo.CFLAGS);
    settings->setValue(projectName+ "/" + "LIBS",compInfo.LIBS);
    settings->setValue(projectName+ "/" + "outputFilename",ui->outputFilename->text());
    settings->setValue(projectName+ "/" + "isExecutable",ui->exeRadioButton->isChecked());
    settings->setValue("ProjectNames",projectNames);
}

void MainWindow::on_loadProjectButton_clicked()
{
    QStringList projectNames = settings->value("ProjectNames").value<QStringList>();
    QString projectName = "";

    bool ok;
    QString item = QInputDialog::getItem(this, tr("Load Project"),
                                          tr("Select a project:"), projectNames, 0, false, &ok);
    if (ok && !item.isEmpty()){
        projectName = item;

        ui->projectEdit->setText(projectName);
        QStringList fileList;
        fileList = settings->value(projectName+ "/" + "InputFiles").value<QStringList>();
        compInfo.INCLUDE = settings->value(projectName+ "/" + "INCLUDE").value<QString>();
        compInfo.CFLAGS  = settings->value(projectName+ "/" + "CFLAGS").value<QString>();
        compInfo.LIBS    = settings->value(projectName+ "/" + "LIBS").value<QString>();
        ui->outputFilename->setText(settings->value(projectName+ "/" + "outputFilename").value<QString>());
        ui->exeRadioButton->setChecked(settings->value(projectName+ "/" + "isExecutable").toBool());
        ui->soRadioButton->setChecked(!settings->value(projectName+ "/" + "isExecutable").toBool());
        ui->fileList->clear();
        ui->fileList->addItems(fileList);
    }
}

void MainWindow::on_deleteProjectButton_clicked()
{
    QStringList projectNames = settings->value("ProjectNames").value<QStringList>();
    QString projectName = "";

    bool ok;
    QString item = QInputDialog::getItem(this, tr("Delete Project"),
                                          tr("Select a project to delete:"), projectNames, 0, false, &ok);

    if (ok && !item.isEmpty()){

        projectName = item;
        QMessageBox::StandardButton sel = messageUserDialog(DialogType::QUEST_SHDT,"Delete " + item.toStdString() + "?" ,"Deleting Project!!!");
        if (sel != QMessageBox::Yes){
            return;
        }
        projectNames.removeOne(projectName);
        settings->setValue("ProjectNames",projectNames);
        settings->remove(projectName);
    }

}



int MainWindow::writeMessage(string ip,string message){
    wmLock.lock();
    int temp = SwarmNet->writeMessage(ip,message);
    wmLock.unlock();
    return temp;
}

int MainWindow::writeMessage(int botnum, string message){
    int temp = writeMessage(ipsVector[botnum - 1],message);
    return temp;
}

std::vector<std::vector<std::string> > MainWindow::receiveMessage(){
    wmLock.lock();
    vector<vector<string>> messages = SwarmNet->receiveMessage();
    wmLock.unlock();
    return messages;
}

bool MainWindow::refreshSwarmNet(){
    wmLock.lock();
    bool temp = SwarmNet->refresh(SwarmOS::OS_INSTRUCTION + SwarmOS::NET_DATA_ACK);
    wmLock.unlock();
    return temp;
}



void MainWindow::on_newProjectButton_clicked()
{
    QString projectName = "";
    ui->projectEdit->setText(projectName);
    compInfo.INCLUDE = "";
    compInfo.CFLAGS  = "";
    compInfo.LIBS    = "";
    ui->outputFilename->setText("");
    ui->exeRadioButton->setChecked(true);
    ui->soRadioButton->setChecked(false);
    ui->fileList->clear();

}

void MainWindow::on_playButton_clicked(bool checked)
{
    static QTreeWidgetItem * item;
    if (checked){ // Play
        item = ui->algorithmTree->currentItem();
        if (item == NULL){
            messageUserDialog(DialogType::WARN_SHDT,
                              "Please select an algorithm to run!","");
            ui->playButton->setChecked(false);
            return;
        }


        for (size_t i = 0; i < ipsVector.size(); i++){
            if (SwarmNet->isConnected(i+1)){
                string algorithm = item->text(0).toStdString();
                writeMessage(ipsVector[i], SwarmOS::OS_INSTRUCTION + algorithm);
            }
        }
        item->setText(1,QString::fromStdString("Running"));

    }
    else{ // Stop
        for (size_t i = 0; i < ipsVector.size(); i++){
            if (SwarmNet->isConnected(i+1)){
                writeMessage(ipsVector[i], SwarmOS::OS_INSTRUCTION + SwarmOS::STOP);
                item->setText(1,QString::fromStdString("Available"));

            }            
        }

        item->setText(1,QString::fromStdString("Available"));

    }
}

void MainWindow::on_actionImport_Settings_triggered()
{
    if (messageUserDialog(DialogType::QUEST_SHDT,
                      "Are you sure you wish to import settings this will restart/close all network related activity?","")
            == QMessageBox::No){
        return;
    }
    QString file = QFileDialog::getOpenFileName(0,"Export Settings",
                                                settings->fileName());

    if (file != ""){
        // Reload settings
        QSettings::setPath(QSettings::NativeFormat,QSettings::UserScope,file);
        delete settings;
        settings = new QSettings(file,QSettings::NativeFormat);
        // Refresh setting dependent objects
        this->refreshSettingDependentObjects();
    }

}

void MainWindow::on_actionExit_2_triggered()
{
    this->close();
}

void MainWindow::on_actionSave_triggered()
{
    QString currentLocus = settings->fileName();
    QString file = QFileDialog::getSaveFileName(0,"Export Settings",
                                                settings->fileName());
    if (file != ""){
        string cmd = ("mv -f " + currentLocus.toStdString() + " " + file.toStdString());
        systemCallWithOutput(cmd);
        delete settings;
        QSettings::setPath(QSettings::NativeFormat,QSettings::UserScope,file);
        settings = new QSettings(file,QSettings::NativeFormat);
    }
}




void MainWindow::on_clearControlConsoleButton_clicked()
{
    ui->controlPanelConsole->clear();
}

void MainWindow::on_clearProgramConsoleButton_clicked()
{
    ui->consoleOutputText->clear();
}

void MainWindow::on_sendCommandButton_clicked()
{
    string command = ui->sshCommandText->text().toStdString();
    command = "\"" + command + "\"";
    if (command == ""){
        addTextHelper(ui->consoleOutputText,"No command input!");
    }
    else if (ui->robotIPCombo->currentText() == "All"){
        for (size_t i = 0; i < ipsVector.size(); i++){
            string output = SendRemoteCommand(ipsVector[i],command);
            addTextHelper(ui->consoleOutputText, output);
        }
    }
    else{
        string output = SendRemoteCommand(ui->robotIPCombo->currentText().toStdString(),command);
        addTextHelper(ui->consoleOutputText, output);
    }
}
void MainWindow::on_commandEdit_returnPressed()
{
    on_commandButton_clicked();
}

void MainWindow::on_RefreshButton_clicked()
{
    time_t start, now;
    vector<vector<string> > messages;
    QStringList robot;
    QList<QTreeWidgetItem *> widgetList;
    if (this->refreshSwarmNet() == true)
    {
        ui->consoleOutputText->appendPlainText("Network Changed");
        ui->controlPanelConsole->append("Network Changed");
    }
    else
    {
        ui->consoleOutputText->appendPlainText("No Network Changes");
        ui->controlPanelConsole->append("No Network Changes");
    }

    int ipSize = ipsVector.size() + 1; // maintain compatibility with ips, which includes host ip (unlike ipsVector)
    string ipPrefix = SwarmOS::OS_INSTRUCTION + SwarmOS::NET_DATA_IP,
           idPrefix = SwarmOS::OS_INSTRUCTION + SwarmOS::NET_DATA_ID,
           ipSizeStr = SwarmOS::OS_INSTRUCTION + SwarmOS::NET_DATA_IP_SIZE + itoa(ipSize);

    for(int i = 1; i < SwarmNet->size(); i++)
    {
        writeMessage(i, idPrefix + itoa(i));

        //give the robot its ip list
        writeMessage(i, ipSizeStr);
        for (int j = 1; j < ipSize; j++) {
            writeMessage(i, ipPrefix+ipsVector[j - 1]);
        }

        /*time(&start);
        time(&now);
        messages.clear();
        while(messages.empty() && difftime(now, start) > 1){
            messages = receiveMessage();
        }
        if(!messages.empty())
        {
            ui->controlPanelConsole->append(QString::fromStdString(messages[0][0]));
        }*/
    }
    ui->availableRobotsTree->clear();
    for (size_t i = 0; i < ipsVector.size(); i++)
    {
        ui->robotIPCombo->addItem(QString::fromStdString(ipsVector[i]));
        robot.clear();
        string num;
        num  = itoa(i + 1);

        if (SwarmNet->isConnected(i+1)){
            //wasConnection = true;
            robot << QString::fromStdString("Robot" + string(num)) << "On"
                     << QString::fromStdString(ipsVector[i]);
            widgetList.append(new QTreeWidgetItem(robot));
        }
        else{
            robot << QString::fromStdString("Robot" + string(num)) << "Off"
                     << QString::fromStdString(ipsVector[i]);
            widgetList.append(new QTreeWidgetItem(robot));
        }

        ui->availableRobotsTree->addTopLevelItem(widgetList[i]);
    }
}
